package org.example;

import lombok.extern.slf4j.Slf4j;
import org.example.config.RegistryConfig;
import org.example.config.RpcConfig;
import org.example.constant.RpcConstant;
import org.example.registry.Registry;
import org.example.registry.RegistryFactory;
import org.example.utils.ConfigUtils;

/**
 * RPC框架应用
 * 相当与holder,存放了项目全局用到的变量,双检锁单例模式实现
 */
@Slf4j
public class RpcApplication {

    private static volatile RpcConfig rpcConfig;

    /**
     * 框架初始化，支持传入自定义配置
     * @param newRpcConfig
     */
    public static void init(RpcConfig newRpcConfig){
        System.out.println(Thread.currentThread().getName() + "执行RpcApplication的init(newRpcConfig)方法"
                             + "参数为：" + newRpcConfig.toString());
        //将传入的配置赋值给全局变量
        rpcConfig = newRpcConfig;
        //记录日志
        log.info("rpc init, config = {}", newRpcConfig);
        //注册中心初始化
        RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
        //根据配置获取注册中心实例
        Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
        //初始化注册中心
        registry.init(registryConfig);
        //记录日志
        log.info("registry init , config = {}",registryConfig);

        //创建并注册 ShutdownHook,JVM退出时执行操作
        Runtime.getRuntime().addShutdownHook(new Thread(registry::destroy));
    }

    /**
     * 初始化
     */
    public static void init(){
        System.out.println(Thread.currentThread().getName() + "执行RpcApplication的init()方法");

        RpcConfig newRpcConfig;
        try {
            newRpcConfig = ConfigUtils.loadConfig(RpcConfig.class, RpcConstant.DEFAULT_CONFIG_PREFIX);
        } catch (Exception e) {
            //配置加载失败，使用默认值
            System.out.println("配置加载失败，使用默认值");
            newRpcConfig = new RpcConfig();
        }
        init(newRpcConfig);
    }

    /**
     * 获取配置
     * @return
     */
    public static RpcConfig getRpcConfig(){
        System.out.println(Thread.currentThread().getName() + "执行RpcApplication中的getRpcConfig方法");
        if (rpcConfig == null) {
            synchronized (RpcApplication.class) {
                if (rpcConfig == null){
                    init();
                }
            }
        }
        return rpcConfig;
    }

}
